﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using Point = System.Drawing.Point;
using System.Windows.Forms;

using DotSpatial.Drawing;
using DotSpatial.Main;
using DotSpatial.Data;
using DotSpatial.Geometries;
using DotSpatial.Map;

namespace HuanGis
{
    class RectangleMF : FMapFunctionBase
    {

        # region 构造函数

        public RectangleMF()
        {
            Configure();
        }

        public RectangleMF(IMap map)
            : base(map)
        {
            Configure();
            //this.Map = map;
        }

        public void Configure()
        {
            _parts = new List<List<Coordinate>>();
        }


        # endregion

        # region 字段

        private IFeatureSet _featureSet;

        private List<Coordinate> _coordinates;
        private List<List<Coordinate>> _parts;
        private bool _standBy;
        private System.Drawing.Point _mousePosition;

        private IMapLineLayer _tempLayer;  //辅绘层？？？

        # endregion

        # region 属性

        public IFeatureSet FeatureSet
        {
            get { return _featureSet; }
            set { _featureSet = value; }
        }

        # endregion


        # region 方法


        protected override void OnActivate()
        {

            if (_standBy == false) _coordinates = new List<Coordinate>();


            if (_tempLayer != null)   //到现在为止，不知道这个有什么用？？？？？？
            {
                Map.MapFrame.DrawingLayers.Remove(_tempLayer);
                Map.MapFrame.Invalidate();
                Map.Invalidate();
                _tempLayer = null;
            }

            _standBy = false;
            base.OnActivate();
        }


        protected override void OnDeactivate()
        {
            if (_standBy) return;
            _standBy = true;

            if (_coordinates != null && _coordinates.Count > 1)
            {
                LineString ls = new LineString(_coordinates);
                FeatureSet fs = new FeatureSet(FeatureTypes.Line);
                fs.Features.Add(new Feature(ls));
                MapLineLayer gll = new MapLineLayer(fs);
                //gll.Symbolizer.FillColor = Color.Blue;
                gll.Symbolizer.ScaleMode = ScaleModes.Symbolic;
                gll.Symbolizer.Smoothing = true;
                gll.MapFrame = Map.MapFrame;

                _tempLayer = gll;
                Map.MapFrame.DrawingLayers.Add(gll);
                // Map.MapFrame.Initialize(_tempLayer);
                Map.MapFrame.Invalidate();
                Map.Invalidate();
            }

        }
        


        /// <summary>
        /// 根据画矩形时的三个点求得对应的四个点
        /// </summary>
        /// <returns></returns>
        private List<PointF> GetFourPoint(List<PointF> points)
        {
            List<PointF> ResultPoints = new List<PointF>();


            double a, b;
            a = (points[1].Y - points[0].Y) / (points[1].X - points[0].X);
            b = points[0].Y - points[0].X * a;

            PointF TempPt1 = new Point();
            PointF TempPt2 = new Point();

            if (points[0].X != points[1].X) //前两个点X值不等
            {

                    //第二个点和第四个点的临时坐标
                TempPt1.X = (float)((a * _mousePosition.Y - a * b + _mousePosition.X) / (1 + a * a));
                TempPt1.Y = (float)(a * TempPt1.X + b);

                TempPt2.X = points[0].X + _mousePosition.X - TempPt1.X;
                TempPt2.Y = points[0].Y + _mousePosition.Y - TempPt1.Y;
    
            }
            else //前两个点X值相等时
            {
               
                    //第二个点和第四个点的临时坐标
                    TempPt1.X = points[0].X;
                    TempPt1.Y = _mousePosition.Y;
                    TempPt2.X = _mousePosition.X;
                    TempPt2.Y = points[0].Y;

            }

            ResultPoints.Add(points[0]);
            ResultPoints.Add(TempPt1);
            ResultPoints.Add(points[2]);
            ResultPoints.Add(TempPt2);

            return ResultPoints;                
        
        }
                        
        protected override void OnDraw(MapDrawArgs e)
        {
            if (_standBy) return;  //如果本层不在编辑中，直接返回！！！


            //------------------------------------------------
            //if (_parts != null)
            //{

            //    List<Point> partPoints = new List<Point>();
            //    foreach (List<Coordinate> part in _parts)
            //    {
            //        foreach (Coordinate c in part)
            //        {
            //            partPoints.Add(Map.ProjToPixel(c));  //转换坐标
            //        }
            //        e.Graphics.DrawPolygon(Pens.Red, partPoints.ToArray());  //绘制矩形（多边形）
            //        //partPoints.Clear();

            //    }

            //    Brush fill = new SolidBrush(Color.FromArgb(70, Color.LightCyan));
            //    if (partPoints.Count > 2)
            //    {
            //        e.Graphics.FillPolygon(fill, partPoints.ToArray());
            //    }
            //    partPoints.Clear();
            //    fill.Dispose();
            //  }


            //这一部分是用来绘制和填充Part的，其实对我们来说 没有用!
            //--------------------------------------------------




            //下面是绘制正在画的线

            Pen redPen = new Pen(Color.Red, 3F);
            List<Point> points = new List<Point>();
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            if (_coordinates != null)
            {
                foreach (Coordinate coord in _coordinates)
                {
                    points.Add(Map.ProjToPixel(coord));  //转换坐标
                }


                if (points.Count == 1 && _standBy == false)
                {
                    e.Graphics.DrawLine(redPen, points[0], _mousePosition);
                }
                else if (points.Count == 2 && _standBy == false)
                {
                    List<PointF> tempoints = new List<PointF>();
                    foreach (Coordinate c in _coordinates)
                    {
                        tempoints.Add(Map.ProjToPixel(c));
                    }

                    tempoints.Add(_mousePosition);  //鼠标位置 ，即矩形第三点

                    List<PointF> RectPoints = new List<PointF>();
                    RectPoints = this.GetFourPoint(tempoints);  //根据三个已知点，求矩形四个点

                    e.Graphics.DrawLine(redPen, RectPoints[0], RectPoints[1]);
                    e.Graphics.DrawLine(redPen, RectPoints[1], RectPoints[2]);
                    e.Graphics.DrawLine(redPen, RectPoints[0], RectPoints[3]);
                    e.Graphics.DrawLine(redPen, RectPoints[3], RectPoints[2]);
                                       
                }

                redPen.Dispose();
                base.OnDraw(e);

            }
             
        }



        protected override void OnMouseMove(GeoMouseArgs e)
        {
            //在本次事件里要做两次擦除工作
            //第一次：画第二个点时的直线擦除
            //第二次：画矩形时的四条直线擦除


            if (_standBy) return;

            if (_coordinates != null)
            {
                if (_coordinates.Count == 1)  //第一次擦除工作……
                {
                    Point Pt = Map.ProjToPixel(_coordinates[0]);

                    Rectangle oldRect = Global.GetRectangle(_mousePosition, Pt);
                    Rectangle newRect = Global.GetRectangle(e.Location, Pt);
                    Rectangle invalid = Rectangle.Union(newRect, oldRect);
                    invalid.Inflate(20, 20);
                    Map.Invalidate(invalid);


                }
                if (_coordinates.Count == 2) //第二次擦除工作
                {
                    List<PointF> points = new List<PointF>();
                    foreach (Coordinate c in _coordinates)
                    {
                        points.Add(Map.ProjToPixel(c));
                    }
                    points.Add(_mousePosition);

                    List<PointF> rectpt = new List<PointF>();
                    rectpt = GetFourPoint(points);

                    Rectangle invalid;

                    for (int i = 0; i < 3; i++)
                    {
                        invalid = Global.GetRectangle(Point.Round (rectpt[i]), Point.Round (rectpt[i + 1]));
                        invalid.Inflate(20, 20);
                        Map.Invalidate(invalid);
                    }
                    invalid = Global.GetRectangle(Point.Round (rectpt[0]), Point.Round (rectpt[3]));
                    invalid.Inflate(20, 20);
                    Map.Invalidate(invalid);

                }
            }

            _mousePosition = e.Location;
            base.OnMouseMove(e);

        }

        protected override void OnMouseUp(GeoMouseArgs e)
        {
            if (_standBy) return;
            if (e.Button == MouseButtons.Right)
            {
                _coordinates = new List<Coordinate>();  //这里是想清空_coordinates
                return;
            }
            else
            {
                if (_coordinates == null) _coordinates = new List<Coordinate>();
                if (_coordinates.Count < 2)
                {
                    _coordinates.Add(e.GeographicLocation);

                    //画第二个点时，再做一次擦除工作
                    if (_coordinates.Count == 2) 
                    {
                        System.Drawing.Point p1 = Map.ProjToPixel(_coordinates[1]);
                        System.Drawing.Point p2 = Map.ProjToPixel(_coordinates[0]);
                        Rectangle invalid = Global.GetRectangle(p1, p2);
                        invalid.Inflate(20, 20);
                        Map.Invalidate(invalid);
                    }
                   
                }
                else
                {
                    _coordinates.Add(e.GeographicLocation);
                    List<PointF> points = new List<PointF>();
                    foreach ( Coordinate c in _coordinates  )
                    {
                        points.Add(Map.ProjToPixel(c));
                    }

                    List<PointF> rectPoints = new List<PointF>();
                    rectPoints = GetFourPoint(points);   //根据已知三点求四个点

                    //画第三个点也要再做一次擦除工作
                    PointF p1, p2;
                    Rectangle invalid;
                    for (int i=0; i < rectPoints.Count - 2; i++)
                    {
                        p1 = rectPoints[i];
                        p2 = rectPoints[i + 1];
                        invalid = Global.GetRectangle(Point.Round(p1), Point.Round(p2));
                        invalid.Inflate(20, 20);
                        Map.Invalidate(invalid);

                    }
                    p1 = rectPoints[0];
                    p2 = rectPoints[3];
                    invalid = Global.GetRectangle(Point.Round(p1), Point.Round(p2));
                    invalid.Inflate(20, 20);
                    Map.Invalidate(invalid);

                    //完成绘制
                    
                   FinishShape();

                }

            }


        }

        static int RectID = 1;

        private void FinishShape()
        {
            List<PointF> points = new List<PointF>();
            foreach (Coordinate c in _coordinates)
            {
                points.Add(Map.ProjToPixel(c));
            
            }

            List<PointF> rectpoint = new List<PointF>();
            rectpoint = GetFourPoint(points);   //求得四个点

            List<Coordinate> CoorRectPt = new List<Coordinate>();

            foreach (PointF p in rectpoint)
            {
                CoorRectPt.Add(Map.PixelToProj(Point.Round(p)));  //再转换一下坐标
            }



            //Finish Part (要不要单独写出去呢)
            //_parts.Add(CoorRectPt);
            //_coordinates = new List<Coordinate>();  //清空
            Map.Invalidate();

            //Finish Shape

            string id = "矩形" + RectID.ToString();
            FRectangleShape RectShp = new FRectangleShape(CoorRectPt.ToArray(),id);
            RectID++;

            this.OnShapeAdded(RectShp);
                       

            _featureSet.InvalidateVertices();
            _featureSet.UpdateEnvelopes();
            _coordinates = new List<Coordinate>();
            _parts = new List<List<Coordinate>>();

        }





       # endregion




    }
}
